home *** CD-ROM | disk | FTP | other *** search
- /* Copyright Cornell University 1986. All rights are reserved. */
- /* See permission and disclaimer notice in file "notice.h" */
-
- /* 10/6/89 kevin rewrote to use a circular buffer */
- /* 11/27/89 kevin tried to fix hang problem by checking emdp->connopen before read */
- /* 12/1/89 kevin modified so stream is released after every session */
-
- #define MACTCP
-
- #include <em.h>
-
- #include "tftp.h"
- #include <menudefs.h>
- #include <resdefs.h>
-
- #include <net.h>
-
- #include "mactcp.h"
-
- #ifndef NULL
- #define NULL 0L
- #endif
-
- #include <util.h>
-
- char * ippname = "\P.IPP"; /* name of IP driver */
- short ipp_refnum; /* refnum of IP driver */
-
- unsigned short maxseg = SENDBUFHIGH; /* maximum segment size */
- short mactcpurgent; /* urgent flag */
-
- TCPiopb statblk; /* statistics */
-
- TCPiopb tcp_read; /* Read control block */
- short read_req;
- short read_reread;
- short read_comp;
- short read_upcalled;
- short read_badreturns;
- short read_callfail;
- short read_fail;
-
- struct rdsstruct {
- rdsEntry rdstab[RDSSIZE];
- unsigned short wdsend; /* left zero to end RDS */
- } read_wds;
-
- /* tcppb is an array of control blocks for sends */
-
- struct tcppb {
- TCPiopb pb; /* Mac parameter block for writes */
- wdsEntry wds1; /* standard wds */
- wdsEntry wds2; /* wds for use if buffer has wrapped */
- short wdsend; /* always 0 */
- struct winds * twp; /* the sending window */
- short busy; /* the pb is in use */
- } tcppb[PBCOUNT];
-
- short send_pend; /* # of sends pending completion */
- short send_next; /* index of next free PB */
- short send_req;
- short send_comp;
- short send_fail;
-
- void mts_done(); /* send completion vector */
- void mtr_done(); /* read completion vector */
- void mtip_done(); /* ip init completion vector */
- void mtcl_done(); /* ip init completion vector */
- void mtopen_done(); /* ip init completion vector */
-
- timer *tcp_tm; /* timer for attempting resend if out of buffers */
- char readup; /* an async read has been performed */
-
- extern char *malloc();
- extern unsigned long getmyA5();
-
- #define MTVALIDITY
- #define PROMPTSEND
-
- #define ipctlGetAddr 15
-
- /* MPW uses d0/d1/a0/a1 as scratch so we must preserve Aztec scratch regs
- just in case
- */
-
- #asm
- mpwcregs reg d0-d3/a0-a2
- #endasm
-
- /* the TCP Async Notification Routine */
-
- pascal void tcp_event(stream, eventCode, conp, terminReason, icmpMsg)
- StreamPtr stream;
- short eventCode;
- struct winds * conp;
- short terminReason;
- ICMPReport *icmpMsg;
- {
- unsigned long oldA5;
-
- oldA5 = getmyA5();
-
- if (invalidconn(conp)) {
- /* check to make sure the UserDataPtr points to a real window */
- SysBeep(1);
- if (keydp != NULL) {
- prerrint25(keydp, "Received upcall from MacTCP for non-existent connection");
- }
- setA5(oldA5);
- return;
- }
-
- mtevent = TRUE;
- switch (eventCode) {
- case TCPClosing: {
- if (!conp->closeflag)
- conp->closeflag = TRUE;
- break;
- }
- case TCPULPTimeout: {
- prerrint25(conp, "TCP Timeout");
- break;
- }
- case TCPTerminate: {
- if (conp->mtcpconnopen) {
- conp->closeflag = terminReason;
- conp->mtcpconnopen = FALSE; /* connection no longer exists */
- if (!conp->closeflag) {
- conp->closeflag = TRUE;
- }
- }
- break;
- }
- case TCPDataArrival: {
- conp->data_rcvd = TRUE;
- break;
- }
- case TCPUrgent: {
- break;
- }
- case TCPICMPReceived: {
- /*
- prerrint25(conp, "TCP ICMP Packet Received");
- */
- break;
- }
- default: {
- prerrint25(conp, "Unknown TCP Notify Code received");
- break;
- }
-
- }
- setA5(oldA5);
- }
-
-
- /* TODO these asynchronous routines are not reliable in MacTCP
- as of 1.0.1.
-
- Multiple outstanding sends cause crashes on Mac+, so we
- better not use 'em anyway.
-
- Async sends seem to cause problems on LocalTalk.
-
- Could be problems w/ MPW v C on args....
-
- OR could MacTCP be failing to save a1 (d1, d2) when making
- direct trap calls after a GetTrapAddress?
-
- */
-
- void mtip_done(tcppb)
- TCPiopb *tcppb;
- {
- unsigned long oldA5;
-
- oldA5 = getmyA5();
- #asm
- movem.l mpwcregs,-(a7)
- #endasm
-
- if (tcp_read.ioResult) {
- ipp_refnum = tcp_read.ioCRefNum;
- macipopen = TRUE;
- }
- #asm
- movem.l (a7)+,mpwcregs
- #endasm
- setA5(oldA5);
- }
-
-
- void mts_done(tcb)
- TCPiopb *tcb;
- {
- wdsEntry *wds;
- unsigned long oldA5;
- struct tcppb * tcppbp;
-
- oldA5 = getmyA5();
- #asm
- movem.l mpwcregs,-(a7)
- #endasm
- #ifdef DYNAMICPB
- tcppbp = (struct tcppb *) tcb->csParam.send.userDataPtr;
- #else
- tcppbp = (struct tcppb *) tcb;
- #endif
-
- wds = (wdsEntry *) tcb->csParam.send.wdsPtr;
-
- if (tcb->ioResult) {
- send_fail++;
- /* prerrint25(twp, "send failure"); */
- }
- else {
- /* subtract the acked data from the count in the buffer */
- tcppbp->twp->fillcount -= wds->length;
- wds++; /* -> wds2 */
- tcppbp->twp->fillcount -= wds->length;
-
- send_comp++;
- }
- --send_pend;
- tcppbp->busy = FALSE;
- #asm
- movem.l (a7)+,mpwcregs
- #endasm
- setA5(oldA5);
- }
-
- #ifdef ASYNCCLOSE
-
- void mtcl_done(tcppb)
- TCPiopb *tcppb;
- {
- unsigned long oldA5;
- struct winds * twp;
-
- oldA5 = getmyA5();
- #asm
- movem.l mpwcregs,-(a7)
- #endasm
-
- twp = (struct winds *) tcppb->csParam.send.userDataPtr;
- twp->mtcpconnopen = FALSE;
-
- #asm
- movem.l (a7)+,mpwcregs
- #endasm
- setA5(oldA5);
- }
- #endif
-
- #ifdef ASYNCOPEN
-
- void mtopen_done(tcppb)
- TCPiopb *tcppb;
- {
- unsigned long oldA5;
- struct winds * twp;
-
- oldA5 = getmyA5();
- #asm
- movem.l mpwcregs,-(a7)
- #endasm
-
- twp = (struct winds *) tcppb->csParam.send.userDataPtr;
-
- if (tcppb->ioResult == openFailed) {
- tcp_err(tcppb->ioResult);
- twp->closeflag = -2;
- return(1);
- }
- else if (tcppb->ioResult) {
- tcp_err(tcppb->ioResult);
- twp->closeflag = -2;
- return(1);
- }
- twp->openflag = TRUE;
- twp->mtcpconnopen = TRUE;
- mtevent = TRUE;
- /* opn_usr() will be called asynchronously */
- #asm
- movem.l (a7)+,mpwcregs
- #endasm
- setA5(oldA5);
- }
-
- #endif
-
- tcp_upcall()
- {
- short index;
- OSErr errcode;
-
- readup = FALSE;
- emdp->data_rcvd = FALSE;
-
- tcp_read.tcpStream = emdp->tcp_stream;
-
- tcp_read.csCode = TCPNoCopyRcv;
- PBControl(&tcp_read, (Boolean) FALSE);
-
- if (tcp_read.ioResult) {
- read_fail++;
- if (emdp->mtcpconnopen) {
- /* ASYNC read always fails once connection broken */
- tcp_err(tcp_read.ioResult);
- }
- }
- else {
-
- for (index = 0; read_wds.rdstab[index].length; index++) {
- wr_usr(read_wds.rdstab[index].ptr, read_wds.rdstab[index].length);
- }
- read_upcalled++;
- }
- /* free the buffers we read */
- tcp_read.csCode = TCPRcvBfrReturn;
- if (errcode = PBControl(&tcp_read, (Boolean) FALSE)) {
- read_badreturns++;
- }
- }
-
-
- /* SHOULD open the Internet Packet driver asynchronously
- so we can do other stuff BUT doesn't seem to call completion! */
-
- ParamBlkRec openblk;
-
- macip_init()
- {
- /* use the openblk block to save some space */
- TCPiopb infoblk;
-
- if (macipopen)
- return(0);
-
- openblk.ioNamePtr = (StringPtr) ippname;
- openblk.u.iop.ioPermssn = 0; /* ioPermssn field */
- /* fsRdWrPerm seems to cause crash...*/
-
- #ifdef IPASYNC
- openblk.ioCompletion = mtip_done;
- PBOpen(&openblk, (Boolean) TRUE);
- #else
- #ifdef OPENDRIVER
- if (OpenDriver(ippname, &ipp_refnum)) {
- error("Can't open MacTCP; check MacTCP configuration for correct net #, gateway address, and unique node address");
- return(-1);
- }
- #else
- openblk.ioCompletion = NULL;
- PBOpen(&openblk, (Boolean) FALSE);
- if (openblk.ioResult) {
- error("Can't open MacTCP; check MacTCP configuration for correct net #, gateway address, and unique node address");
- return(-1);
- }
- ipp_refnum = openblk.u.iop.ioRefNum;
- #endif
- macipopen = TRUE;
-
- /* get our IP address */
- memzero(&infoblk, sizeof(struct TCPiopb));
-
- infoblk.ioCRefNum = ipp_refnum;
- infoblk.csCode = ipctlGetAddr;
- PBControl(&infoblk, (Boolean) FALSE);
- if (infoblk.ioResult) {
- rnet->ip_addr = 0;
- }
- else
- rnet->ip_addr = infoblk.tcpStream;
- /* kluge to avoid defining GetMyIPAddr pb */
-
- #endif
- return(0);
- }
-
-
- mactcp_init()
- {
- short cnt;
- TCPiopb infoblk;
-
- if (mactcpopen)
- return(0);
-
- if (!macipopen) {
- if (macip_init()) {
- return(-1);
- }
- }
-
- memzero(&infoblk, sizeof(struct TCPiopb));
-
- /* allocate resend retry timer */
- if (tcp_tm == NULL) {
- /* first time through */
- if ((tcp_tm = tm_alloc()) == NULL)
- return(-1);
- }
-
- #ifdef IPASYNC
- while (openblk.ioResult == 1)
- ;
-
- /* wait for async IP init to complete */
- if (openblk.ioResult) {
- error("Can't open MacTCP driver");
- return(-1);
- }
- ipp_refnum = openblk.ioCRefNum;
- #endif
-
- tcp_read.ioNamePtr = (StringPtr) NULL;
- infoblk.ioCRefNum = ipp_refnum;
- infoblk.csCode = TCPGlobalInfo;
-
- /* get MSS. NB: MacTCP hangs if send WDS is > MSS!!!!! */
-
- if (PBControl(&infoblk, (Boolean) FALSE)) {
- error("Can't get MacTCP MSS, using 512 default");
- }
- else
- maxseg = infoblk.csParam.globalInfo.tcpParamPtr->tcpMaxSegSize;
-
- /* set up read PB */
- tcp_read.ioCRefNum = ipp_refnum;
- tcp_read.csCode = TCPNoCopyRcv;
- tcp_read.csParam.receive.rdsPtr = (Ptr) &read_wds;
- tcp_read.csParam.receive.rdsLength = RDSSIZE;
- tcp_read.ioCompletion = NULL;
- tcp_read.csParam.receive.commandTimeoutValue = 1;
-
- /* allocate send pbs */
- for (cnt = 0; cnt < PBCOUNT; cnt++) {
- #ifdef DYNAMICPB
- tcppb[cnt].pb = (TCPiopb *) malloc(sizeof(struct TCPiopb));
- if (tcppb[cnt].pb == NULL) {
- return(-1);
- }
- tcppb[cnt].pb = StripAddress(tcppb[cnt].pb);
- memzero(tcppb[cnt].pb, sizeof(struct TCPiopb));
- #endif
-
- tcppb[cnt].pb.csCode = TCPSend;
- tcppb[cnt].pb.ioCRefNum = ipp_refnum;
- tcppb[cnt].pb.ioCompletion = NULL;
- #ifdef MTVALIDITY
- /* set timeout value */
- tcppb[cnt].pb.csParam.send.ulpTimeoutValue = 255;
- tcppb[cnt].pb.csParam.send.ulpTimeoutAction = 1; /* was 1, abort */
- tcppb[cnt].pb.csParam.send.validityFlags = timeoutValue | timeoutAction;
- #endif
-
- tcppb[cnt].pb.csParam.send.pushFlag = TRUE;
- tcppb[cnt].pb.csParam.send.wdsPtr = (Ptr) &tcppb[cnt].wds1;
-
- /* setup wds for this PB */
- tcppb[cnt].wdsend = 0;
- }
- mactcpopen = TRUE;
-
- return(0);
- }
-
- /* call macTCP to make a stream */
-
- tcp_makestream()
- {
- /* TCPiopb tblk;
- TODO could the allocation of the stream on the stack rather than
- permanently be causing problems? probably not ...*/
-
- if (emdp->tcp_stream)
- /* we already have a stream allocated */
- return(0);
-
- if (emdp->mtstream == NULL) {
- /* allocate TCP stream create memory; may not be necessary to save this... */
- if ((emdp->mtstream = (char *) malloc(sizeof(struct TCPiopb))) == NULL) {
- tcpmemoryreclaim(emdp);
- return(-1);
- }
- emdp->mtstream = StripAddress(emdp->mtstream);
-
- /* allocate send buffer */
- emdp->sendbuf = (unsigned char *) malloc(SENDBUFSIZE);
- if (emdp->sendbuf == NULL) {
- tcpmemoryreclaim(emdp);
- return(-1);
- }
- emdp->sendbuf = StripAddress(emdp->sendbuf);
-
- /* allocate connection block */
- emdp->tcp_conn = (TCPiopb *) malloc(sizeof(TCPiopb));
- if (emdp->tcp_conn == NULL) {
- tcpmemoryreclaim(emdp);
- return(-1);
- }
- emdp->tcp_conn = StripAddress(emdp->tcp_conn);
-
- /* allocate the receive buffer */
- if ((emdp->rcvbuf = (char *) malloc(BUFLEN)) == NULL) {
- tcpmemoryreclaim(emdp);
- return(-1);
- }
- emdp->rcvbuf = StripAddress(emdp->rcvbuf);
- }
- /* initialize the elements... */
-
- memzero(emdp->mtstream, sizeof(struct TCPiopb));
- emdp->sendp = emdp->fillp = emdp->sendbuf;
- emdp->fillendp = emdp->sendbuf + SENDBUFSIZE;
- memzero(emdp->tcp_conn, sizeof(struct TCPiopb));
-
- emdp->mtstream->ioCRefNum = ipp_refnum;
- emdp->mtstream->csCode = TCPCreate;
- emdp->mtstream->csParam.create.rcvBuff = emdp->rcvbuf;
- emdp->mtstream->csParam.create.rcvBuffLen = (unsigned long) BUFLEN;
- emdp->mtstream->csParam.create.notifyProc = (ProcPtr) tcp_event;
- emdp->mtstream->csParam.create.userDataPtr = emdp;
- PBControl(emdp->mtstream, (Boolean) FALSE);
- if (emdp->mtstream->ioResult) {
- tcp_err(emdp->mtstream->ioResult);
- tcpmemoryreclaim(emdp);
- return(-1);
- }
-
- /* we get the stream * in return */
- emdp->tcp_stream = emdp->mtstream->tcpStream;
- /* if we don't do this assignment, it doesn't work... ??? */
- emdp->tcp_stream = StripAddress(emdp->tcp_stream);
-
- return(0);
- }
-
- /* add a character to the send buffer */
-
- mactcp_put(thechar)
- char thechar;
- {
- if (!emdp->mtcpconnopen)
- return(-1);
-
- if (emdp->fillcount >= SENDBUFSIZE) {
- return(-1);
- }
-
- /* stick the character in the buffer */
- emdp->fillcount++;
- emdp->waitcount++;
- *emdp->fillp++ = thechar;
- if (emdp->fillp >= emdp->fillendp) {
- /* wrap around if we're at the end of the buffer */
- emdp->fillp = emdp->sendbuf;
- }
-
- #ifdef PROMPTSEND
- if (emdp->waitcount >= maxseg)
- /* send if the buffer gets full */
- mactcp_ex();
- #endif
-
- return(0);
- }
-
-
- /* add a character to the buffer and send the packet promptly */
-
- mactcp_fput(thechar)
- char thechar;
- {
- if (!emdp->mtcpconnopen)
- return(-1);
-
- if (! (emdp->fillcount < SENDBUFSIZE)) {
- return(-1);
- }
-
- /* stick the character in the buffer */
- emdp->fillcount++;
- emdp->waitcount++;
- *emdp->fillp++ = thechar;
- if (emdp->fillp >= emdp->fillendp) {
- /* wrap around if we're at the end of the buffer */
- emdp->fillp = emdp->sendbuf;
- }
-
- mactcp_ex();
- return(0);
- }
-
-
- /* the better to trap retries for PB available */
-
- tcp_rex()
- {
- mactcp_ex();
- }
-
-
- /* send outstanding data */
-
- mactcp_ex()
- {
- unsigned short sendcount;
- unsigned short send2;
-
- if (!emdp->mtcpconnopen)
- return(-1);
-
- if (emdp->waitcount == 0) {
- /* nothing to send */
- emdp->send_wait = FALSE;
- return(0);
- }
- else {
- emdp->send_wait = TRUE;
- mtevent = TRUE; /* guarantee we get service */
- }
-
- if (send_pend >= PBCOUNT) {
- /* we don't have a free parameter block, reschedule */
- #ifdef TCP_REX
- tm_tset(1, tcp_rex, emdp, tcp_tm);
- #endif
- return(-2);
- }
- if (tcppb[send_next].busy) {
- /* find a free pb */
- int sendindex;
-
- for (sendindex = send_next + 1; sendindex < PBCOUNT; sendindex++) {
- if (tcppb[sendindex].busy)
- continue;
- }
- if (sendindex == PBCOUNT) {
- /* didn't find one yet, wrap around */
- for (sendindex = 0; sendindex < send_next; sendindex++) {
- if (tcppb[sendindex].busy)
- continue;
- }
- if (sendindex == send_next) {
- /* no free pb, shouldn't happen here since PBCOUNT tested */
- /* TODO--make a new send buffer? */
- return(-3);
- }
- }
- send_next = sendindex;
- }
- if (emdp->fillp < emdp->sendp)
- /* data has wrapped */
- sendcount = emdp->fillendp - emdp->sendp;
- else
- sendcount = emdp->fillp - emdp->sendp;
-
- #ifdef PROMPTSEND
- if (sendcount > maxseg) {
- /* MacTCP chokes if a segment is > MSS ... */
- sendcount = maxseg;
- }
- #endif
-
- /* per window in send */
- tcppb[send_next].twp = emdp;
-
- #ifdef DYNAMICPB
- tcppb[send_next].pb.csParam.send.userDataPtr = &tcppb[send_next];
- #else
- tcppb[send_next].pb.csParam.send.userDataPtr = emdp;
- #endif
- tcppb[send_next].pb.csParam.send.urgentFlag = mactcpurgent;
-
- tcppb[send_next].pb.tcpStream = emdp->tcp_stream;
-
- tcppb[send_next].wds1.ptr = emdp->sendp;
- tcppb[send_next].wds1.length = sendcount;
-
- #ifdef TCPBUFWRAP
- if (emdp->fillp < emdp->sendp && sendcount < maxseg) {
- /* data wrapped, we can use two elements in the WDS */
- /* we can send some of the wrapped data */
- /* HOWEVER this is no win, since MacTCP sends two pkts anyway */
-
- send2 = emdp->fillp - emdp->sendbuf;
- if ((sendcount + send2) >= maxseg) {
- send2 = maxseg - sendcount;
- sendcount = maxseg;
- }
- else {
- sendcount += send2;
- }
- tcppb[send_next].wds2.length = send2;
- tcppb[send_next].wds2.ptr = emdp->sendbuf;
- tcppb[send_next].wdsend = 0; /* terminate WDS2 */
- }
- else {
- tcppb[send_next].wds2.length = 0; /* terminate WDS1 */
- tcppb[send_next].wds2.ptr = NULL;
- }
- #else
- tcppb[send_next].wds2.length = 0; /* terminate WDS1 */
- tcppb[send_next].wds2.ptr = NULL;
- #endif
-
- send_req++;
- if (mtcpsendasync) {
- /* if user is configured for async send, do so... */
- tcppb[send_next].pb.ioCompletion = mts_done;
- tcppb[send_next].busy = TRUE;
- if (PBControl(&tcppb[send_next].pb, (Boolean) TRUE)) {
- /* TODO retries? just bomb out? */
- send_fail++;
- tcppb[send_next].busy = FALSE;
- tcp_err(tcppb[send_next].pb.ioResult);
- return(-1);
- }
- send_pend++;
- if (++send_next >= PBCOUNT)
- send_next = 0;
- }
- else {
- /* use the synchronous call, which is a bummer because
- it does not return until after the data is acked... */
- if (tcppb[send_next].pb.ioCompletion) {
- /* who the fuck is tampering with this? */
- beartrap();
- tcppb[send_next].pb.ioCompletion = NULL;
- }
-
- if (PBControl(&tcppb[send_next].pb, (Boolean) FALSE)) {
- /* TODO retries? just bomb out? */
- send_fail++;
- tcp_err(tcppb[send_next].pb.ioResult);
- return(-1);
- }
- if (tcppb[send_next].pb.ioCompletion) {
- /* who the fuck is tampering with this? */
- beartrap();
- tcppb[send_next].pb.ioCompletion = NULL;
- }
- /* subtract the acked data from the count in the buffer */
- emdp->fillcount -= sendcount;
- send_comp++;
- }
- emdp->waitcount -= sendcount;
-
- /* set emdp->sendp -> next char needing send */
- emdp->sendp += sendcount;
- if (emdp->sendp >= emdp->fillendp) {
- /* wrap pointer if necessary */
- emdp->sendp -= SENDBUFSIZE;
- }
-
- return(0);
- }
-
-
- /* open a connection with a host */
-
- mactcp_open(addr, port)
- long * addr;
- short port;
- /* a short local socket argument is also a parameter, not used w/ mactcp */
- {
- if (!mactcpopen) {
- if (mactcp_init()) {
- return(-1);
- }
- }
- if (tcp_makestream())
- return(-1);
-
- emdp->tcp_conn->ioCRefNum = ipp_refnum;
- emdp->tcp_conn->csCode = TCPActiveOpen;
- emdp->tcp_conn->tcpStream = emdp->tcp_stream;
- #ifdef MTVALIDITY
- emdp->tcp_conn->csParam.open.ulpTimeoutValue = 15; /* was 15 */
- emdp->tcp_conn->csParam.open.ulpTimeoutAction = 1; /* abort 1, report 0 */
- emdp->tcp_conn->csParam.open.validityFlags = timeoutValue | timeoutAction;
- #endif
- emdp->tcp_conn->csParam.open.remoteHost = *addr;
- emdp->tcp_conn->csParam.open.remotePort = port;
- emdp->tcp_conn->csParam.open.localPort = 0; /* let mactcp assign */
- emdp->tcp_conn->csParam.open.dontFrag = 1;
- emdp->tcp_conn->csParam.open.timeToLive = 0; /* let mactcp assign */
- emdp->tcp_conn->csParam.open.security = 0; /* let mactcp assign */
- emdp->tcp_conn->csParam.open.optionCnt = 0; /* no IP options */
- /* commandTimeoutValue not used as per manual */
-
- emdp->tcp_conn->csParam.open.userDataPtr = emdp;
- #ifdef ASYNCOPEN
- emdp->tcp_conn->ioCompletion = mtopen_done;
-
- PBControl(emdp->tcp_conn, (Boolean) TRUE);
- #else
- emdp->tcp_conn->ioCompletion = NULL;
-
- SetCursor(*GetCursor(watchCursor));
- /* put up a watch cursor to show this may take some time */
-
- PBControl(emdp->tcp_conn, (Boolean) FALSE);
-
- SetCursor(&arrow);
-
- if (emdp->tcp_conn->ioResult == openFailed) {
- tcp_err(emdp->tcp_conn->ioResult);
- emdp->closeflag = -2;
- return(1);
- }
- else if (emdp->tcp_conn->ioResult) {
- tcp_err(emdp->tcp_conn->ioResult);
- emdp->closeflag = -2;
- return(1);
- }
- emdp->mtcpconnopen = TRUE;
- opn_usr(); /* this comes after completion if async call */
- #endif
- return(0);
- }
-
-
-
- /* stubs
-
- needs to be implemented for mactcp
-
- IcEchoRequest()
- {
- }
-
- */
-
- mactcp_close()
- {
- TCPiopb closePB;
-
- if (!emdp->mtcpconnopen || !emdp->tcp_stream)
- return(-1);
-
- /* PBControl(&statblk, (Boolean) FALSE)); get pre-closing status */
-
- memzero(&closePB, sizeof(struct TCPiopb));
-
- closePB.ioCRefNum = ipp_refnum;
- closePB.csCode = TCPClose;
- closePB.tcpStream = emdp->tcp_stream;
- closePB.csParam.close.userDataPtr = emdp;
- #ifdef MTVALIDITY
- closePB.csParam.close.ulpTimeoutValue = 30; /* was 30 */
- closePB.csParam.close.ulpTimeoutAction = 1; /* abort, zero = report */
- closePB.csParam.close.validityFlags = timeoutValue | timeoutAction;
- #endif
-
- #ifdef ASYNCCLOSE
- closePB.ioCompletion = mtcl_done;
- if (PBControl(&closePB, (Boolean) TRUE)) {
- prerrint25(emdp, "TCP Close call failed");
- }
- #else
- closePB.ioCompletion = NULL;
- if (PBControl(&closePB, (Boolean) FALSE)) {
- prerrint25(emdp, "TCP Close call failed");
- /* make sure user can quit application anyway... */
- emdp->mtcpconnopen = FALSE; /* connection no longer exists */
- emdp->closeflag = TRUE;
- }
- else {
- emdp->mtcpconnopen = FALSE;
- /* statblk.csParam.status.connectionState = CLOSED; fix stat report */
- }
- #endif
- return(0);
- }
-
-
-
- /* release a stream */
-
- tcp_release(twp)
- struct winds * twp;
- {
- TCPiopb relPB;
-
- if (!twp->tcp_stream)
- return(-1);
-
- memzero(&relPB, sizeof(struct TCPiopb));
-
- relPB.ioCRefNum = ipp_refnum;
- relPB.csCode = TCPRelease;
- relPB.tcpStream = twp->tcp_stream;
- relPB.csParam.release.userDataPtr = twp;
-
- if (PBControl(&relPB, (Boolean) FALSE)) {
- error("MacTCP stream release failed");
- return(-1);
- }
- twp->tcp_stream = 0;
- twp->mtcpconnopen = FALSE;
- return(0);
- }
-
-
- /* abort a connection not used? */
-
- mactcpclrsendbuf()
- {
- TCPiopb abortPB;
-
- if (!emdp->mtcpconnopen)
- return(-1);
-
- memzero(&abortPB, sizeof(struct TCPiopb));
-
- abortPB.ioCRefNum = ipp_refnum;
- abortPB.csCode = TCPAbort;
- abortPB.tcpStream = emdp->tcp_stream;
- abortPB.csParam.abort.userDataPtr = emdp;
-
- if (PBControl(&abortPB, (Boolean) FALSE)) {
- error("session abort failed");
- return(-1);
- }
- /* mactcp_wrapup(); */
- emdp->mtcpconnopen = FALSE;
- emdp->closeflag = TRUE;
- return(0);
- }
-
-
- /* works only in emdp context */
-
- tcp_err(errcode)
- OSErr errcode;
- {
- switch (errcode) {
- case inProgress:
- prerrint25(emdp, "I/O in progress");
- break;
- case ipBadLapErr:
- prerrint25(emdp, "bad network configuration");
- break;
- case ipBadCnfgErr:
- prerrint25(emdp, "bad IP configuration error");
- break;
- case ipNoCnfgErr:
- prerrint25(emdp, "missing IP or LAP configuration error");
- break;
- case ipLoadErr:
- prerrint25(emdp, "error in MacTCP load");
- break;
- case ipBadAddr:
- prerrint25(emdp, "error in getting address");
- break;
- case connectionClosing:
- prerrint25(emdp, "connection is closing");
- break;
- case invalidLength:
- prerrint25(emdp, "invalid length");
- break;
- case connectionExists:
- prerrint25(emdp, "request conflicts with existing connection");
- break;
- case connectionDoesntExist:
- prerrint25(emdp, "connection does not exist");
- break;
- case insufficientResources:
- prerrint25(emdp, "insufficient resources to perform request");
- break;
- case invalidStreamPtr:
- prerrint25(emdp, "invalid stream ptr");
- break;
- case streamAlreadyOpen:
- prerrint25(emdp, "stream already open");
- break;
- case connectionTerminated:
- prerrint25(emdp, "connection terminated");
- break;
- case invalidBufPtr:
- prerrint25(emdp, "invalid buffer ptr");
- break;
- case invalidWDS:
- prerrint25(emdp, "invalid WDS");
- /* also covers RDS */
- break;
- case openFailed:
- prerrint25(emdp, "Session closed: Can't connect to host");
- break;
- case commandTimeout:
- prerrint25(emdp, "command timed out");
- break;
- case duplicateSocket:
- prerrint25(emdp, "duplicate socket");
- break;
-
- /* Error codes from internal IP functions */
- case ipDontFragErr:
- prerrint25(emdp, "Packet too large to send w/o fragmenting");
- break;
- case ipDestDeadErr:
- prerrint25(emdp, "destination not responding");
- break;
- case ipNoFragMemErr:
- prerrint25(emdp, "no memory to send fragmented pkt");
- break;
- case ipRouteErr:
- prerrint25(emdp, "can't route packet off-net");
- break;
-
- case outOfMemory:
- prerrint25(emdp, "Out of memory");
- break;
- default:
- prerrint25(emdp, "Unknown TCP error");
- break;
- }
- }
-
-
- char * mtcptermarr[] = {
- "",
- "",
- "Session closed: Host has abruptly closed session with a Reset",
- "Session closed: Network failure",
- "Session closed: Security/precedence mismatch",
- "Session closed: a timeout has occurred",
- "Session closed: an abort has occurred",
- "Session closed",
- "Session closed: Service failure"
- };
-
-
- term_report(cause)
- short cause;
- {
- int sessionkilled = FALSE;
-
- switch (cause) {
- case -2: {
- /* our tag for failure to connect */
- sessionkilled = TRUE;
- break;
- }
- case 2: {
- prerrint25(emdp, mtcptermarr[cause]);
- sessionkilled = TRUE;
- break;
- }
- case 3: {
- prerrint25(emdp, mtcptermarr[cause]);
- sessionkilled = TRUE;
- break;
- }
- case 4: {
- prerrint25(emdp, mtcptermarr[cause]);
- sessionkilled = TRUE;
- break;
- }
- case 5: {
- prerrint25(emdp, mtcptermarr[cause]);
- sessionkilled = TRUE;
- break;
- }
- case 6: {
- prerrint25(emdp, mtcptermarr[cause]);
- sessionkilled = TRUE;
- break;
- }
- case 7: {
- /* this is a normal close requested from the user layer */
- prerrint25(emdp, mtcptermarr[cause]);
- break;
- }
- case 8: {
- prerrint25(emdp, mtcptermarr[cause]);
- sessionkilled = TRUE;
- break;
- }
- }
- if (sessionkilled) {
- /* alert used session died abnormally */
- beep();
- windmenumark(emdp, 0xA0); /* set a † mark */
- }
- else
- windmenumark(emdp, noMark); /* clear any marks */
- }
-
-
- /* wrap up a MacTCP connection, close if necessary, reset UI */
- /* WARNING: twp may disappear & emdp change when this function is called! */
-
- mactcp_wrapup()
- {
- int theflag = emdp->closeflag;
-
- emdp->closeflag = 0;
- term_report(theflag);
- if (emdp->mtcpconnopen) {
- mactcp_close();
- emdp->closeflag = 0; /* could get reset by MacTCP during close? */
- }
- mtreset();
- cls_usr(); /* WARNING: twp may disappear, emdp may change! */
- }
-
-
- /* reset the MacTCP session variables */
-
- mtreset()
- {
- emdp->fillcount = 0;
- emdp->waitcount = 0;
- emdp->send_wait = FALSE;
- emdp->sendp = emdp->fillp = emdp->sendbuf;
-
- emdp->closeflag = FALSE;
-
- /* no timers allocated for MacTCP */
- }
-
-
- #ifndef DUALTCP
-
- char * strend(sptr)
- register char * sptr;
- {
- while (*sptr++) {
- ;
- }
- return(--sptr);
- }
-
- #endif
-
- /*
- Display some tcp statistics and a few lines of unacked data. Should be
- revised and integrated in with the normal logging system.
- */
- /* this is now mac-dependent */
-
- #define CLOSED 0
- #define SYNRCVD 4
- #define SYNSENT 6
- #define ESTAB 8
- #define FINWAIT1 10
- #define FINWAIT2 12
- #define CLOSEWAIT 14
- #define CLOSING 16
- #define LASTACK 18
- #define TIMEWAIT 20
-
- mactcp_status()
- {
- char dumpbuf[4000];
- char * dumpp;
- extern char * strend();
- TCPiopb infoblk;
- OSErr errcode;
- struct TCPConnectionStats *statp;
-
- memzero(&infoblk, sizeof(struct TCPiopb));
-
- infoblk.ioCRefNum = ipp_refnum;
- infoblk.csCode = TCPGlobalInfo;
-
- /* used primarily for debugging purposes */
- if (errcode = PBControl(&infoblk, (Boolean) FALSE)) {
- ;
- }
-
- statblk.ioCRefNum = ipp_refnum;
- statblk.csCode = TCPStatus;
- statblk.tcpStream = keydp->tcp_stream;
-
- if (errcode = PBControl(&statblk, (Boolean) FALSE)) {
- /*
- getcontext(keydp);
- tcp_err(errcode);
- tcp_err() uses emdp
- return(0);
-
- instead, fall through and show last stat block gathered...
- */
- /* statblk.csParam.status.connectionState = CLOSED; fix stat report */
- /* no connection exists returns failure; TODO should cache closing stats? */
- return(0);
- }
- statp = statblk.csParam.status.connStatPtr;
-
- /* we hope dumpbuf does not get overwritten; this program protected by prayer
- "I shot a pointer into the buffer, I hope the program does not suffer ..." */
-
- dumpp = dumpbuf;
-
- sprintf(dumpbuf, "Connection State: ");
- dumpp = strend(dumpp);
- /* reposition pointer to end to add more */
- switch (statblk.csParam.status.connectionState) {
- case CLOSED: {
- sprintf(dumpp, "Closed\r");
- break;
- }
- case SYNSENT: {
- sprintf(dumpp, "Trying to Open\r");
- break;
- }
- case SYNRCVD: {
- sprintf(dumpp, "SYNRCVD\r");
- break;
- }
- case ESTAB: {
- sprintf(dumpp, "Established\r");
- break;
- }
- case FINWAIT1: {
- sprintf(dumpp, "Closing (FIN-WAIT 1)\r");
- break;
- }
- case FINWAIT2: {
- sprintf(dumpp, "Closing (FIN-WAIT 2)\r");
- break;
- }
- case CLOSEWAIT: {
- sprintf(dumpp, "Closing (Close Wait)\r");
- break;
- }
- case CLOSING: {
- sprintf(dumpp, "Closing\r");
- break;
- }
- case LASTACK: {
- sprintf(dumpp, "Closing (Last Ack)\r");
- break;
- }
- case TIMEWAIT: {
- sprintf(dumpp, "Closing (Time Wait)\r");
- break;
- }
- default: {
- sprintf(dumpp, "Closing\r");
- }
- }
- dumpp = strend(dumpp);
- sprintf(dumpp, "\r");
- dumpp = strend(dumpp);
-
- sprintf(dumpp, "Packets sent: %5U Resends: %5U\r",
- statp->dataPktsSent, statp->dataPktsResent);
- dumpp = strend(dumpp);
- sprintf(dumpp, "Packets rcvd: %5U\r",
- statp->dataPktsRcvd);
- /* Re-rcvd: %5U Not for me: %5U */
- dumpp = strend(dumpp);
- /*
- sprintf(dumpp, "Bad checksum: %5u No data: %5u Out of seq: %5u -- %u used\r",
- tcpbadck, tcpnodata, tcpoutseq, tcpsoutseq);
- dumpp = strend(dumpp);
- */
- sprintf(dumpp, "Local Window: %5u HostWindow: %5u\r",
- statblk.csParam.status.rcvWindow, statblk.csParam.status.sendWindow);
- dumpp = strend(dumpp);
- sprintf(dumpp, " ACK: %08X SEQ: %08X\r",
- statblk.csParam.status.rcvNext, statblk.csParam.status.sendNext);
- dumpp = strend(dumpp);
- sprintf(dumpp, " Bytes Sent: %10U -- %u unacked\r",
- statp->bytesSent, emdp->fillcount - emdp->waitcount);
- dumpp = strend(dumpp);
- sprintf(dumpp, " Bytes Rcvd: %10U\r",
- statp->bytesRcvd);
- dumpp = strend(dumpp);
-
- fillwindow(TEXTOTHER, dumpbuf, (long) (dumpp - dumpbuf), monaco, 9, 0L);
- /* TEXT types have 4 bytes of length in them */
- }
-
-
- /* free the memory associated with a MacTCP session */
-
- tcpmemoryreclaim(twp)
- struct winds * twp;
- {
- short cnt;
-
- if (twp->mtstream)
- free(twp->mtstream);
- if (twp->rcvbuf)
- free(twp->rcvbuf);
- if (twp->sendbuf)
- free(twp->sendbuf);
- if (twp->tcp_conn)
- free(twp->tcp_conn);
-
- twp->mtstream = NULL;
- twp->rcvbuf = NULL;
- twp->sendbuf = NULL;
- twp->tcp_conn = NULL;
- }
-
- #ifdef NOTMERGED
- /* send MacTCP data waiting to be sent ... */
-
- tcp_service()
- {
- struct winds ** conp = conns;
- struct winds * conend = &conp[conncount];
- register struct winds * twp;
-
- while (conp < conend) {
- twp = *conp++;
-
- if (twp->conntype != CONN_MACTCP)
- continue;
-
- if (twp->closeflag) {
- getcontext(twp);
- mactcp_wrapup(); /* WARNING: twp may disappear, emdp may change! */
- }
- if (twp->send_wait) {
- /* a packet is waiting for buffer; try to send again */
- getcontext(twp);
- mactcp_ex();
- }
- else if (twp->fillcount && (twp->fillcount == twp->waitcount)) {
- /* SHOULD NEVER REACH THIS POINT! once was a symptom of
- MacTCP async "let's waste some variables" behavior */
- getcontext(twp);
- mactcp_ex();
- }
- }
- }
-
- #endif
-
-
- memzero(zptr, length)
- register char * zptr;
- int length;
- {
- while (length--)
- *zptr++ = 0;
- }
-
-
- /* draw the packet counters */
-
- tcp_drawcount(twp)
- struct winds * twp;
- {
- OSErr errcode;
- struct TCPConnectionStats *statp;
-
- if (!twp->connopen)
- return(0);
-
- statblk.ioCRefNum = ipp_refnum;
- statblk.csCode = TCPStatus;
- statblk.tcpStream = twp->tcp_stream;
-
- if (errcode = PBControl(&statblk, (Boolean) FALSE)) {
- return(0);
- }
- statp = statblk.csParam.status.connStatPtr;
-
- if (twp->in_cnt != statp->dataPktsRcvd) {
- twp->in_cnt = statp->dataPktsRcvd;
- getcontext(twp);
- drawincount();
- }
- if (twp->out_cnt != (statp->dataPktsSent + statp->dataPktsResent)) {
- twp->out_cnt = (statp->dataPktsSent + statp->dataPktsResent);
- getcontext(twp);
- if (twp->resends != statp->dataPktsResent) {
- twp->resends = statp->dataPktsResent;
- /* if (statblk.csParam.status.amtUnackedData != 0)
- skip this test so even synced senders can note the acklessness... */
- twp->resending = TRUE;
- }
- drawoutcount();
- }
- else {
- if (twp->resending) {
- if (statblk.csParam.status.amtUnackedData == 0) {
- twp->resending = FALSE;
- getcontext(twp);
- drawoutcount();
- }
- }
- }
- }
-
- mtcpurgent()
- {
- mactcpurgent = TRUE;
- }
-
-
-
- mtcpclrurgent()
- {
- mactcpurgent = 0;
- }
-
-
- beartrap()
- {
- SysBeep(5);
- }
-
-